home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / d_spr8.s < prev    next >
Text File  |  2000-05-22  |  21KB  |  901 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. //
  21. // d_spr8.s
  22. // x86 assembly-language horizontal 8-bpp transparent span-drawing code.
  23. //
  24.  
  25. #include "asm_i386.h"
  26. #include "quakeasm.h"
  27. #include "asm_draw.h"
  28.  
  29. #if id386
  30.  
  31. //----------------------------------------------------------------------
  32. // 8-bpp horizontal span drawing code for polygons, with transparency.
  33. //----------------------------------------------------------------------
  34.  
  35.     .text
  36.  
  37. // out-of-line, rarely-needed clamping code
  38.  
  39. LClampHigh0:
  40.     movl    C(bbextents),%esi
  41.     jmp        LClampReentry0
  42. LClampHighOrLow0:
  43.     jg        LClampHigh0
  44.     xorl    %esi,%esi
  45.     jmp        LClampReentry0
  46.  
  47. LClampHigh1:
  48.     movl    C(bbextentt),%edx
  49.     jmp        LClampReentry1
  50. LClampHighOrLow1:
  51.     jg        LClampHigh1
  52.     xorl    %edx,%edx
  53.     jmp        LClampReentry1
  54.  
  55. LClampLow2:
  56.     movl    $2048,%ebp
  57.     jmp        LClampReentry2
  58. LClampHigh2:
  59.     movl    C(bbextents),%ebp
  60.     jmp        LClampReentry2
  61.  
  62. LClampLow3:
  63.     movl    $2048,%ecx
  64.     jmp        LClampReentry3
  65. LClampHigh3:
  66.     movl    C(bbextentt),%ecx
  67.     jmp        LClampReentry3
  68.  
  69. LClampLow4:
  70.     movl    $2048,%eax
  71.     jmp        LClampReentry4
  72. LClampHigh4:
  73.     movl    C(bbextents),%eax
  74.     jmp        LClampReentry4
  75.  
  76. LClampLow5:
  77.     movl    $2048,%ebx
  78.     jmp        LClampReentry5
  79. LClampHigh5:
  80.     movl    C(bbextentt),%ebx
  81.     jmp        LClampReentry5
  82.  
  83.  
  84. #define pspans    4+16
  85.  
  86.     .align 4
  87. .globl C(D_SpriteDrawSpans)
  88. C(D_SpriteDrawSpans):
  89.     pushl    %ebp                // preserve caller's stack frame
  90.     pushl    %edi
  91.     pushl    %esi                // preserve register variables
  92.     pushl    %ebx
  93.  
  94. //
  95. // set up scaled-by-8 steps, for 8-long segments; also set up cacheblock
  96. // and span list pointers, and 1/z step in 0.32 fixed-point
  97. //
  98. // FIXME: any overlap from rearranging?
  99.     flds    C(d_sdivzstepu)
  100.     fmuls    fp_8
  101.     movl    C(cacheblock),%edx
  102.     flds    C(d_tdivzstepu)
  103.     fmuls    fp_8
  104.     movl    pspans(%esp),%ebx    // point to the first span descriptor
  105.     flds    C(d_zistepu)
  106.     fmuls    fp_8
  107.     movl    %edx,pbase            // pbase = cacheblock
  108.     flds    C(d_zistepu)
  109.     fmuls    fp_64kx64k
  110.     fxch    %st(3)
  111.     fstps    sdivz8stepu
  112.     fstps    zi8stepu
  113.     fstps    tdivz8stepu
  114.     fistpl    izistep
  115.     movl    izistep,%eax
  116.     rorl    $16,%eax        // put upper 16 bits in low word
  117.     movl    sspan_t_count(%ebx),%ecx
  118.     movl    %eax,izistep
  119.  
  120.     cmpl    $0,%ecx
  121.     jle        LNextSpan
  122.  
  123. LSpanLoop:
  124.  
  125. //
  126. // set up the initial s/z, t/z, and 1/z on the FP stack, and generate the
  127. // initial s and t values
  128. //
  129. // FIXME: pipeline FILD?
  130.     fildl    sspan_t_v(%ebx)
  131.     fildl    sspan_t_u(%ebx)
  132.  
  133.     fld        %st(1)            // dv | du | dv
  134.     fmuls    C(d_sdivzstepv)    // dv*d_sdivzstepv | du | dv
  135.     fld        %st(1)            // du | dv*d_sdivzstepv | du | dv
  136.     fmuls    C(d_sdivzstepu)    // du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
  137.     fld        %st(2)            // du | du*d_sdivzstepu | dv*d_sdivzstepv | du | dv
  138.     fmuls    C(d_tdivzstepu)    // du*d_tdivzstepu | du*d_sdivzstepu |
  139.                             //  dv*d_sdivzstepv | du | dv
  140.     fxch    %st(1)            // du*d_sdivzstepu | du*d_tdivzstepu |
  141.                             //  dv*d_sdivzstepv | du | dv
  142.     faddp    %st(0),%st(2)    // du*d_tdivzstepu |
  143.                             //  du*d_sdivzstepu + dv*d_sdivzstepv | du | dv
  144.     fxch    %st(1)            // du*d_sdivzstepu + dv*d_sdivzstepv |
  145.                             //  du*d_tdivzstepu | du | dv
  146.     fld        %st(3)            // dv | du*d_sdivzstepu + dv*d_sdivzstepv |
  147.                             //  du*d_tdivzstepu | du | dv
  148.     fmuls    C(d_tdivzstepv)    // dv*d_tdivzstepv |
  149.                             //  du*d_sdivzstepu + dv*d_sdivzstepv |
  150.                             //  du*d_tdivzstepu | du | dv
  151.     fxch    %st(1)            // du*d_sdivzstepu + dv*d_sdivzstepv |
  152.                             //  dv*d_tdivzstepv | du*d_tdivzstepu | du | dv
  153.     fadds    C(d_sdivzorigin) // sdivz = d_sdivzorigin + dv*d_sdivzstepv +
  154.                             //  du*d_sdivzstepu; stays in %st(2) at end
  155.     fxch    %st(4)            // dv | dv*d_tdivzstepv | du*d_tdivzstepu | du |
  156.                             //  s/z
  157.     fmuls    C(d_zistepv)        // dv*d_zistepv | dv*d_tdivzstepv |
  158.                             //  du*d_tdivzstepu | du | s/z
  159.     fxch    %st(1)            // dv*d_tdivzstepv |  dv*d_zistepv |
  160.                             //  du*d_tdivzstepu | du | s/z
  161.     faddp    %st(0),%st(2)    // dv*d_zistepv |
  162.                             //  dv*d_tdivzstepv + du*d_tdivzstepu | du | s/z
  163.     fxch    %st(2)            // du | dv*d_tdivzstepv + du*d_tdivzstepu |
  164.                             //  dv*d_zistepv | s/z
  165.     fmuls    C(d_zistepu)        // du*d_zistepu |
  166.                             //  dv*d_tdivzstepv + du*d_tdivzstepu |
  167.                             //  dv*d_zistepv | s/z
  168.     fxch    %st(1)            // dv*d_tdivzstepv + du*d_tdivzstepu |
  169.                             //  du*d_zistepu | dv*d_zistepv | s/z
  170.     fadds    C(d_tdivzorigin)    // tdivz = d_tdivzorigin + dv*d_tdivzstepv +
  171.                             //  du*d_tdivzstepu; stays in %st(1) at end
  172.     fxch    %st(2)            // dv*d_zistepv | du*d_zistepu | t/z | s/z
  173.     faddp    %st(0),%st(1)    // dv*d_zistepv + du*d_zistepu | t/z | s/z
  174.  
  175.     flds    fp_64k            // fp_64k | dv*d_zistepv + du*d_zistepu | t/z | s/z
  176.     fxch    %st(1)            // dv*d_zistepv + du*d_zistepu | fp_64k | t/z | s/z
  177.     fadds    C(d_ziorigin)        // zi = d_ziorigin + dv*d_zistepv +
  178.                             //  du*d_zistepu; stays in %st(0) at end
  179.                             // 1/z | fp_64k | t/z | s/z
  180.  
  181.     fld        %st(0)            // FIXME: get rid of stall on FMUL?
  182.     fmuls    fp_64kx64k
  183.     fxch    %st(1)
  184.  
  185. //
  186. // calculate and clamp s & t
  187. //
  188.     fdivr    %st(0),%st(2)    // 1/z | z*64k | t/z | s/z
  189.     fxch    %st(1)
  190.  
  191.     fistpl    izi                // 0.32 fixed-point 1/z
  192.     movl    izi,%ebp
  193.  
  194. //
  195. // set pz to point to the first z-buffer pixel in the span
  196. //
  197.     rorl    $16,%ebp        // put upper 16 bits in low word
  198.     movl    sspan_t_v(%ebx),%eax
  199.     movl    %ebp,izi
  200.     movl    sspan_t_u(%ebx),%ebp
  201.     imull    C(d_zrowbytes)
  202.     shll    $1,%ebp                    // a word per pixel
  203.     addl    C(d_pzbuffer),%eax
  204.     addl    %ebp,%eax
  205.     movl    %eax,pz
  206.  
  207. //
  208. // point %edi to the first pixel in the span
  209. //
  210.     movl    C(d_viewbuffer),%ebp
  211.     movl    sspan_t_v(%ebx),%eax
  212.     pushl    %ebx        // preserve spans pointer
  213.     movl    C(tadjust),%edx
  214.     movl    C(sadjust),%esi
  215.     movl    C(d_scantable)(,%eax,4),%edi    // v * screenwidth
  216.     addl    %ebp,%edi
  217.     movl    sspan_t_u(%ebx),%ebp
  218.     addl    %ebp,%edi                // pdest = &pdestspan[scans->u];
  219.  
  220. //
  221. // now start the FDIV for the end of the span
  222. //
  223.     cmpl    $8,%ecx
  224.     ja        LSetupNotLast1
  225.  
  226.     decl    %ecx
  227.     jz        LCleanup1        // if only one pixel, no need to start an FDIV
  228.     movl    %ecx,spancountminus1
  229.  
  230. // finish up the s and t calcs
  231.     fxch    %st(1)            // z*64k | 1/z | t/z | s/z
  232.  
  233.     fld        %st(0)            // z*64k | z*64k | 1/z | t/z | s/z
  234.     fmul    %st(4),%st(0)    // s | z*64k | 1/z | t/z | s/z
  235.     fxch    %st(1)            // z*64k | s | 1/z | t/z | s/z
  236.     fmul    %st(3),%st(0)    // t | s | 1/z | t/z | s/z
  237.     fxch    %st(1)            // s | t | 1/z | t/z | s/z
  238.     fistpl    s                // 1/z | t | t/z | s/z
  239.     fistpl    t                // 1/z | t/z | s/z
  240.  
  241.     fildl    spancountminus1
  242.  
  243.     flds    C(d_tdivzstepu)    // _d_tdivzstepu | spancountminus1
  244.     flds    C(d_zistepu)    // _d_zistepu | _d_tdivzstepu | spancountminus1
  245.     fmul    %st(2),%st(0)    // _d_zistepu*scm1 | _d_tdivzstepu | scm1
  246.     fxch    %st(1)            // _d_tdivzstepu | _d_zistepu*scm1 | scm1
  247.     fmul    %st(2),%st(0)    // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
  248.     fxch    %st(2)            // scm1 | _d_zistepu*scm1 | _d_tdivzstepu*scm1
  249.     fmuls    C(d_sdivzstepu)    // _d_sdivzstepu*scm1 | _d_zistepu*scm1 |
  250.                             //  _d_tdivzstepu*scm1
  251.     fxch    %st(1)            // _d_zistepu*scm1 | _d_sdivzstepu*scm1 |
  252.                             //  _d_tdivzstepu*scm1
  253.     faddp    %st(0),%st(3)    // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
  254.     fxch    %st(1)            // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
  255.     faddp    %st(0),%st(3)    // _d_sdivzstepu*scm1
  256.     faddp    %st(0),%st(3)
  257.  
  258.     flds    fp_64k
  259.     fdiv    %st(1),%st(0)    // this is what we've gone to all this trouble to
  260.                             //  overlap
  261.     jmp        LFDIVInFlight1
  262.  
  263. LCleanup1:
  264. // finish up the s and t calcs
  265.     fxch    %st(1)            // z*64k | 1/z | t/z | s/z
  266.  
  267.     fld        %st(0)            // z*64k | z*64k | 1/z | t/z | s/z
  268.     fmul    %st(4),%st(0)    // s | z*64k | 1/z | t/z | s/z
  269.     fxch    %st(1)            // z*64k | s | 1/z | t/z | s/z
  270.     fmul    %st(3),%st(0)    // t | s | 1/z | t/z | s/z
  271.     fxch    %st(1)            // s | t | 1/z | t/z | s/z
  272.     fistpl    s                // 1/z | t | t/z | s/z
  273.     fistpl    t                // 1/z | t/z | s/z
  274.     jmp        LFDIVInFlight1
  275.  
  276.     .align    4
  277. LSetupNotLast1:
  278. // finish up the s and t calcs
  279.     fxch    %st(1)            // z*64k | 1/z | t/z | s/z
  280.  
  281.     fld        %st(0)            // z*64k | z*64k | 1/z | t/z | s/z
  282.     fmul    %st(4),%st(0)    // s | z*64k | 1/z | t/z | s/z
  283.     fxch    %st(1)            // z*64k | s | 1/z | t/z | s/z
  284.     fmul    %st(3),%st(0)    // t | s | 1/z | t/z | s/z
  285.     fxch    %st(1)            // s | t | 1/z | t/z | s/z
  286.     fistpl    s                // 1/z | t | t/z | s/z
  287.     fistpl    t                // 1/z | t/z | s/z
  288.  
  289.     fadds    zi8stepu
  290.     fxch    %st(2)
  291.     fadds    sdivz8stepu
  292.     fxch    %st(2)
  293.     flds    tdivz8stepu
  294.     faddp    %st(0),%st(2)
  295.     flds    fp_64k
  296.     fdiv    %st(1),%st(0)    // z = 1/1/z
  297.                             // this is what we've gone to all this trouble to
  298.                             //  overlap
  299. LFDIVInFlight1:
  300.  
  301.     addl    s,%esi
  302.     addl    t,%edx
  303.     movl    C(bbextents),%ebx
  304.     movl    C(bbextentt),%ebp
  305.     cmpl    %ebx,%esi
  306.     ja        LClampHighOrLow0
  307. LClampReentry0:
  308.     movl    %esi,s
  309.     movl    pbase,%ebx
  310.     shll    $16,%esi
  311.     cmpl    %ebp,%edx
  312.     movl    %esi,sfracf
  313.     ja        LClampHighOrLow1
  314. LClampReentry1:
  315.     movl    %edx,t
  316.     movl    s,%esi                    // sfrac = scans->sfrac;
  317.     shll    $16,%edx
  318.     movl    t,%eax                    // tfrac = scans->tfrac;
  319.     sarl    $16,%esi
  320.     movl    %edx,tfracf
  321.  
  322. //
  323. // calculate the texture starting address
  324. //
  325.     sarl    $16,%eax
  326.     addl    %ebx,%esi
  327.     imull    C(cachewidth),%eax        // (tfrac >> 16) * cachewidth
  328.     addl    %eax,%esi                // psource = pbase + (sfrac >> 16) +
  329.                                     //           ((tfrac >> 16) * cachewidth);
  330.  
  331. //
  332. // determine whether last span or not
  333. //
  334.     cmpl    $8,%ecx
  335.     jna        LLastSegment
  336.  
  337. //
  338. // not the last segment; do full 8-wide segment
  339. //
  340. LNotLastSegment:
  341.  
  342. //
  343. // advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
  344. // get there
  345. //
  346.  
  347. // pick up after the FDIV that was left in flight previously
  348.  
  349.     fld        %st(0)            // duplicate it
  350.     fmul    %st(4),%st(0)    // s = s/z * z
  351.     fxch    %st(1)
  352.     fmul    %st(3),%st(0)    // t = t/z * z
  353.     fxch    %st(1)
  354.     fistpl    snext
  355.     fistpl    tnext
  356.     movl    snext,%eax
  357.     movl    tnext,%edx
  358.  
  359.     subl    $8,%ecx        // count off this segments' pixels
  360.     movl    C(sadjust),%ebp
  361.     pushl    %ecx        // remember count of remaining pixels
  362.     movl    C(tadjust),%ecx
  363.  
  364.     addl    %eax,%ebp
  365.     addl    %edx,%ecx
  366.  
  367.     movl    C(bbextents),%eax
  368.     movl    C(bbextentt),%edx
  369.  
  370.     cmpl    $2048,%ebp
  371.     jl        LClampLow2
  372.     cmpl    %eax,%ebp
  373.     ja        LClampHigh2
  374. LClampReentry2:
  375.  
  376.     cmpl    $2048,%ecx
  377.     jl        LClampLow3
  378.     cmpl    %edx,%ecx
  379.     ja        LClampHigh3
  380. LClampReentry3:
  381.  
  382.     movl    %ebp,snext
  383.     movl    %ecx,tnext
  384.  
  385.     subl    s,%ebp
  386.     subl    t,%ecx
  387.     
  388. //
  389. // set up advancetable
  390. //
  391.     movl    %ecx,%eax
  392.     movl    %ebp,%edx
  393.     sarl    $19,%edx            // sstep >>= 16;
  394.     movl    C(cachewidth),%ebx
  395.     sarl    $19,%eax            // tstep >>= 16;
  396.     jz        LIsZero
  397.     imull    %ebx,%eax            // (tstep >> 16) * cachewidth;
  398. LIsZero:
  399.     addl    %edx,%eax            // add in sstep
  400.                                 // (tstep >> 16) * cachewidth + (sstep >> 16);
  401.     movl    tfracf,%edx
  402.     movl    %eax,advancetable+4    // advance base in t
  403.     addl    %ebx,%eax            // ((tstep >> 16) + 1) * cachewidth +
  404.                                 //  (sstep >> 16);
  405.     shll    $13,%ebp            // left-justify sstep fractional part
  406.     movl    %ebp,sstep
  407.     movl    sfracf,%ebx
  408.     shll    $13,%ecx            // left-justify tstep fractional part
  409.     movl    %eax,advancetable    // advance extra in t
  410.     movl    %ecx,tstep
  411.  
  412.     movl    pz,%ecx
  413.     movl    izi,%ebp
  414.  
  415.     cmpw    (%ecx),%bp
  416.     jl        Lp1
  417.     movb    (%esi),%al            // get first source texel
  418.     cmpb    $(TRANSPARENT_COLOR),%al
  419.     jz        Lp1
  420.     movw    %bp,(%ecx)
  421.     movb    %al,(%edi)            // store first dest pixel
  422. Lp1:
  423.     addl    izistep,%ebp
  424.     adcl    $0,%ebp
  425.     addl    tstep,%edx            // advance tfrac fractional part by tstep frac
  426.  
  427.     sbbl    %eax,%eax            // turn tstep carry into -1 (0 if none)
  428.     addl    sstep,%ebx            // advance sfrac fractional part by sstep frac
  429.     adcl    advancetable+4(,%eax,4),%esi    // point to next source texel
  430.  
  431.     cmpw    2(%ecx),%bp
  432.     jl        Lp2
  433.     movb    (%esi),%al
  434.     cmpb    $(TRANSPARENT_COLOR),%al
  435.     jz        Lp2
  436.     movw    %bp,2(%ecx)
  437.     movb    %al,1(%edi)
  438. Lp2:
  439.     addl    izistep,%ebp
  440.     adcl    $0,%ebp
  441.     addl    tstep,%edx
  442.     sbbl    %eax,%eax
  443.     addl    sstep,%ebx
  444.     adcl    advancetable+4(,%eax,4),%esi
  445.  
  446.     cmpw    4(%ecx),%bp
  447.     jl        Lp3
  448.     movb    (%esi),%al
  449.     cmpb    $(TRANSPARENT_COLOR),%al
  450.     jz        Lp3
  451.     movw    %bp,4(%ecx)
  452.     movb    %al,2(%edi)
  453. Lp3:
  454.     addl    izistep,%ebp
  455.     adcl    $0,%ebp
  456.     addl    tstep,%edx
  457.     sbbl    %eax,%eax
  458.     addl    sstep,%ebx
  459.     adcl    advancetable+4(,%eax,4),%esi
  460.  
  461.     cmpw    6(%ecx),%bp
  462.     jl        Lp4
  463.     movb    (%esi),%al
  464.     cmpb    $(TRANSPARENT_COLOR),%al
  465.     jz        Lp4
  466.     movw    %bp,6(%ecx)
  467.     movb    %al,3(%edi)
  468. Lp4:
  469.     addl    izistep,%ebp
  470.     adcl    $0,%ebp
  471.     addl    tstep,%edx
  472.     sbbl    %eax,%eax
  473.     addl    sstep,%ebx
  474.     adcl    advancetable+4(,%eax,4),%esi
  475.  
  476.     cmpw    8(%ecx),%bp
  477.     jl        Lp5
  478.     movb    (%esi),%al
  479.     cmpb    $(TRANSPARENT_COLOR),%al
  480.     jz        Lp5
  481.     movw    %bp,8(%ecx)
  482.     movb    %al,4(%edi)
  483. Lp5:
  484.     addl    izistep,%ebp
  485.     adcl    $0,%ebp
  486.     addl    tstep,%edx
  487.     sbbl    %eax,%eax
  488.     addl    sstep,%ebx
  489.     adcl    advancetable+4(,%eax,4),%esi
  490.  
  491. //
  492. // start FDIV for end of next segment in flight, so it can overlap
  493. //
  494.     popl    %eax
  495.     cmpl    $8,%eax            // more than one segment after this?
  496.     ja        LSetupNotLast2    // yes
  497.  
  498.     decl    %eax
  499.     jz        LFDIVInFlight2    // if only one pixel, no need to start an FDIV
  500.     movl    %eax,spancountminus1
  501.     fildl    spancountminus1
  502.  
  503.     flds    C(d_zistepu)        // _d_zistepu | spancountminus1
  504.     fmul    %st(1),%st(0)    // _d_zistepu*scm1 | scm1
  505.     flds    C(d_tdivzstepu)    // _d_tdivzstepu | _d_zistepu*scm1 | scm1
  506.     fmul    %st(2),%st(0)    // _d_tdivzstepu*scm1 | _d_zistepu*scm1 | scm1
  507.     fxch    %st(1)            // _d_zistepu*scm1 | _d_tdivzstepu*scm1 | scm1
  508.     faddp    %st(0),%st(3)    // _d_tdivzstepu*scm1 | scm1
  509.     fxch    %st(1)            // scm1 | _d_tdivzstepu*scm1
  510.     fmuls    C(d_sdivzstepu)    // _d_sdivzstepu*scm1 | _d_tdivzstepu*scm1
  511.     fxch    %st(1)            // _d_tdivzstepu*scm1 | _d_sdivzstepu*scm1
  512.     faddp    %st(0),%st(3)    // _d_sdivzstepu*scm1
  513.     flds    fp_64k            // 64k | _d_sdivzstepu*scm1
  514.     fxch    %st(1)            // _d_sdivzstepu*scm1 | 64k
  515.     faddp    %st(0),%st(4)    // 64k
  516.  
  517.     fdiv    %st(1),%st(0)    // this is what we've gone to all this trouble to
  518.                             //  overlap
  519.     jmp        LFDIVInFlight2
  520.  
  521.     .align    4
  522. LSetupNotLast2:
  523.     fadds    zi8stepu
  524.     fxch    %st(2)
  525.     fadds    sdivz8stepu
  526.     fxch    %st(2)
  527.     flds    tdivz8stepu
  528.     faddp    %st(0),%st(2)
  529.     flds    fp_64k
  530.     fdiv    %st(1),%st(0)    // z = 1/1/z
  531.                             // this is what we've gone to all this trouble to
  532.                             //  overlap
  533. LFDIVInFlight2:
  534.     pushl    %eax
  535.  
  536.     cmpw    10(%ecx),%bp
  537.     jl        Lp6
  538.     movb    (%esi),%al
  539.     cmpb    $(TRANSPARENT_COLOR),%al
  540.     jz        Lp6
  541.     movw    %bp,10(%ecx)
  542.     movb    %al,5(%edi)
  543. Lp6:
  544.     addl    izistep,%ebp
  545.     adcl    $0,%ebp
  546.     addl    tstep,%edx
  547.     sbbl    %eax,%eax
  548.     addl    sstep,%ebx
  549.     adcl    advancetable+4(,%eax,4),%esi
  550.  
  551.     cmpw    12(%ecx),%bp
  552.     jl        Lp7
  553.     movb    (%esi),%al
  554.     cmpb    $(TRANSPARENT_COLOR),%al
  555.     jz        Lp7
  556.     movw    %bp,12(%ecx)
  557.     movb    %al,6(%edi)
  558. Lp7:
  559.     addl    izistep,%ebp
  560.     adcl    $0,%ebp
  561.     addl    tstep,%edx
  562.     sbbl    %eax,%eax
  563.     addl    sstep,%ebx
  564.     adcl    advancetable+4(,%eax,4),%esi
  565.  
  566.     cmpw    14(%ecx),%bp
  567.     jl        Lp8
  568.     movb    (%esi),%al
  569.     cmpb    $(TRANSPARENT_COLOR),%al
  570.     jz        Lp8
  571.     movw    %bp,14(%ecx)
  572.     movb    %al,7(%edi)
  573. Lp8:
  574.     addl    izistep,%ebp
  575.     adcl    $0,%ebp
  576.     addl    tstep,%edx
  577.     sbbl    %eax,%eax
  578.     addl    sstep,%ebx
  579.     adcl    advancetable+4(,%eax,4),%esi
  580.  
  581.     addl    $8,%edi
  582.     addl    $16,%ecx
  583.     movl    %edx,tfracf
  584.     movl    snext,%edx
  585.     movl    %ebx,sfracf
  586.     movl    tnext,%ebx
  587.     movl    %edx,s
  588.     movl    %ebx,t
  589.  
  590.     movl    %ecx,pz
  591.     movl    %ebp,izi
  592.  
  593.     popl    %ecx                // retrieve count
  594.  
  595. //
  596. // determine whether last span or not
  597. //
  598.     cmpl    $8,%ecx                // are there multiple segments remaining?
  599.     ja        LNotLastSegment        // yes
  600.  
  601. //
  602. // last segment of scan
  603. //
  604. LLastSegment:
  605.  
  606. //
  607. // advance s/z, t/z, and 1/z, and calculate s & t at end of span and steps to
  608. // get there. The number of pixels left is variable, and we want to land on the
  609. // last pixel, not step one past it, so we can't run into arithmetic problems
  610. //
  611.     testl    %ecx,%ecx
  612.     jz        LNoSteps        // just draw the last pixel and we're done
  613.  
  614. // pick up after the FDIV that was left in flight previously
  615.  
  616.  
  617.     fld        %st(0)            // duplicate it
  618.     fmul    %st(4),%st(0)    // s = s/z * z
  619.     fxch    %st(1)
  620.     fmul    %st(3),%st(0)    // t = t/z * z
  621.     fxch    %st(1)
  622.     fistpl    snext
  623.     fistpl    tnext
  624.  
  625.     movl    C(tadjust),%ebx
  626.     movl    C(sadjust),%eax
  627.  
  628.     addl    snext,%eax
  629.     addl    tnext,%ebx
  630.  
  631.     movl    C(bbextents),%ebp
  632.     movl    C(bbextentt),%edx
  633.  
  634.     cmpl    $2048,%eax
  635.     jl        LClampLow4
  636.     cmpl    %ebp,%eax
  637.     ja        LClampHigh4
  638. LClampReentry4:
  639.     movl    %eax,snext
  640.  
  641.     cmpl    $2048,%ebx
  642.     jl        LClampLow5
  643.     cmpl    %edx,%ebx
  644.     ja        LClampHigh5
  645. LClampReentry5:
  646.  
  647.     cmpl    $1,%ecx            // don't bother 
  648.     je        LOnlyOneStep    // if two pixels in segment, there's only one step,
  649.                             //  of the segment length
  650.     subl    s,%eax
  651.     subl    t,%ebx
  652.  
  653.     addl    %eax,%eax        // convert to 15.17 format so multiply by 1.31
  654.     addl    %ebx,%ebx        //  reciprocal yields 16.48
  655.     imull    reciprocal_table-8(,%ecx,4) // sstep = (snext - s) / (spancount-1)
  656.     movl    %edx,%ebp
  657.  
  658.     movl    %ebx,%eax
  659.     imull    reciprocal_table-8(,%ecx,4) // tstep = (tnext - t) / (spancount-1)
  660.  
  661. LSetEntryvec:
  662. //
  663. // set up advancetable
  664. //
  665.     movl    spr8entryvec_table(,%ecx,4),%ebx
  666.     movl    %edx,%eax
  667.     pushl    %ebx                // entry point into code for RET later
  668.     movl    %ebp,%ecx
  669.     sarl    $16,%ecx            // sstep >>= 16;
  670.     movl    C(cachewidth),%ebx
  671.     sarl    $16,%edx            // tstep >>= 16;
  672.     jz        LIsZeroLast
  673.     imull    %ebx,%edx            // (tstep >> 16) * cachewidth;
  674. LIsZeroLast:
  675.     addl    %ecx,%edx            // add in sstep
  676.                                 // (tstep >> 16) * cachewidth + (sstep >> 16);
  677.     movl    tfracf,%ecx
  678.     movl    %edx,advancetable+4    // advance base in t
  679.     addl    %ebx,%edx            // ((tstep >> 16) + 1) * cachewidth +
  680.                                 //  (sstep >> 16);
  681.     shll    $16,%ebp            // left-justify sstep fractional part
  682.     movl    sfracf,%ebx
  683.     shll    $16,%eax            // left-justify tstep fractional part
  684.     movl    %edx,advancetable    // advance extra in t
  685.  
  686.     movl    %eax,tstep
  687.     movl    %ebp,sstep
  688.     movl    %ecx,%edx
  689.  
  690.     movl    pz,%ecx
  691.     movl    izi,%ebp
  692.  
  693.     ret                            // jump to the number-of-pixels handler
  694.  
  695. //----------------------------------------
  696.  
  697. LNoSteps:
  698.     movl    pz,%ecx
  699.     subl    $7,%edi            // adjust for hardwired offset
  700.     subl    $14,%ecx
  701.     jmp        LEndSpan
  702.  
  703.  
  704. LOnlyOneStep:
  705.     subl    s,%eax
  706.     subl    t,%ebx
  707.     movl    %eax,%ebp
  708.     movl    %ebx,%edx
  709.     jmp        LSetEntryvec
  710.  
  711. //----------------------------------------
  712.  
  713. .globl    Spr8Entry2_8
  714. Spr8Entry2_8:
  715.     subl    $6,%edi        // adjust for hardwired offsets
  716.     subl    $12,%ecx
  717.     movb    (%esi),%al
  718.     jmp        LLEntry2_8
  719.  
  720. //----------------------------------------
  721.  
  722. .globl    Spr8Entry3_8
  723. Spr8Entry3_8:
  724.     subl    $5,%edi        // adjust for hardwired offsets
  725.     subl    $10,%ecx
  726.     jmp        LLEntry3_8
  727.  
  728. //----------------------------------------
  729.  
  730. .globl    Spr8Entry4_8
  731. Spr8Entry4_8:
  732.     subl    $4,%edi        // adjust for hardwired offsets
  733.     subl    $8,%ecx
  734.     jmp        LLEntry4_8
  735.  
  736. //----------------------------------------
  737.  
  738. .globl    Spr8Entry5_8
  739. Spr8Entry5_8:
  740.     subl    $3,%edi        // adjust for hardwired offsets
  741.     subl    $6,%ecx
  742.     jmp        LLEntry5_8
  743.  
  744. //----------------------------------------
  745.  
  746. .globl    Spr8Entry6_8
  747. Spr8Entry6_8:
  748.     subl    $2,%edi        // adjust for hardwired offsets
  749.     subl    $4,%ecx
  750.     jmp        LLEntry6_8
  751.  
  752. //----------------------------------------
  753.  
  754. .globl    Spr8Entry7_8
  755. Spr8Entry7_8:
  756.     decl    %edi        // adjust for hardwired offsets
  757.     subl    $2,%ecx
  758.     jmp        LLEntry7_8
  759.  
  760. //----------------------------------------
  761.  
  762. .globl    Spr8Entry8_8
  763. Spr8Entry8_8:
  764.     cmpw    (%ecx),%bp
  765.     jl        Lp9
  766.     movb    (%esi),%al
  767.     cmpb    $(TRANSPARENT_COLOR),%al
  768.     jz        Lp9
  769.     movw    %bp,(%ecx)
  770.     movb    %al,(%edi)
  771. Lp9:
  772.     addl    izistep,%ebp
  773.     adcl    $0,%ebp
  774.     addl    tstep,%edx
  775.     sbbl    %eax,%eax
  776.     addl    sstep,%ebx
  777.     adcl    advancetable+4(,%eax,4),%esi
  778. LLEntry7_8:
  779.     cmpw    2(%ecx),%bp
  780.     jl        Lp10
  781.     movb    (%esi),%al
  782.     cmpb    $(TRANSPARENT_COLOR),%al
  783.     jz        Lp10
  784.     movw    %bp,2(%ecx)
  785.     movb    %al,1(%edi)
  786. Lp10:
  787.     addl    izistep,%ebp
  788.     adcl    $0,%ebp
  789.     addl    tstep,%edx
  790.     sbbl    %eax,%eax
  791.     addl    sstep,%ebx
  792.     adcl    advancetable+4(,%eax,4),%esi
  793. LLEntry6_8:
  794.     cmpw    4(%ecx),%bp
  795.     jl        Lp11
  796.     movb    (%esi),%al
  797.     cmpb    $(TRANSPARENT_COLOR),%al
  798.     jz        Lp11
  799.     movw    %bp,4(%ecx)
  800.     movb    %al,2(%edi)
  801. Lp11:
  802.     addl    izistep,%ebp
  803.     adcl    $0,%ebp
  804.     addl    tstep,%edx
  805.     sbbl    %eax,%eax
  806.     addl    sstep,%ebx
  807.     adcl    advancetable+4(,%eax,4),%esi
  808. LLEntry5_8:
  809.     cmpw    6(%ecx),%bp
  810.     jl        Lp12
  811.     movb    (%esi),%al
  812.     cmpb    $(TRANSPARENT_COLOR),%al
  813.     jz        Lp12
  814.     movw    %bp,6(%ecx)
  815.     movb    %al,3(%edi)
  816. Lp12:
  817.     addl    izistep,%ebp
  818.     adcl    $0,%ebp
  819.     addl    tstep,%edx
  820.     sbbl    %eax,%eax
  821.     addl    sstep,%ebx
  822.     adcl    advancetable+4(,%eax,4),%esi
  823. LLEntry4_8:
  824.     cmpw    8(%ecx),%bp
  825.     jl        Lp13
  826.     movb    (%esi),%al
  827.     cmpb    $(TRANSPARENT_COLOR),%al
  828.     jz        Lp13
  829.     movw    %bp,8(%ecx)
  830.     movb    %al,4(%edi)
  831. Lp13:
  832.     addl    izistep,%ebp
  833.     adcl    $0,%ebp
  834.     addl    tstep,%edx
  835.     sbbl    %eax,%eax
  836.     addl    sstep,%ebx
  837.     adcl    advancetable+4(,%eax,4),%esi
  838. LLEntry3_8:
  839.     cmpw    10(%ecx),%bp
  840.     jl        Lp14
  841.     movb    (%esi),%al
  842.     cmpb    $(TRANSPARENT_COLOR),%al
  843.     jz        Lp14
  844.     movw    %bp,10(%ecx)
  845.     movb    %al,5(%edi)
  846. Lp14:
  847.     addl    izistep,%ebp
  848.     adcl    $0,%ebp
  849.     addl    tstep,%edx
  850.     sbbl    %eax,%eax
  851.     addl    sstep,%ebx
  852.     adcl    advancetable+4(,%eax,4),%esi
  853. LLEntry2_8:
  854.     cmpw    12(%ecx),%bp
  855.     jl        Lp15
  856.     movb    (%esi),%al
  857.     cmpb    $(TRANSPARENT_COLOR),%al
  858.     jz        Lp15
  859.     movw    %bp,12(%ecx)
  860.     movb    %al,6(%edi)
  861. Lp15:
  862.     addl    izistep,%ebp
  863.     adcl    $0,%ebp
  864.     addl    tstep,%edx
  865.     sbbl    %eax,%eax
  866.     addl    sstep,%ebx
  867.     adcl    advancetable+4(,%eax,4),%esi
  868.  
  869. LEndSpan:
  870.     cmpw    14(%ecx),%bp
  871.     jl        Lp16
  872.     movb    (%esi),%al        // load first texel in segment
  873.     cmpb    $(TRANSPARENT_COLOR),%al
  874.     jz        Lp16
  875.     movw    %bp,14(%ecx)
  876.     movb    %al,7(%edi)
  877. Lp16:
  878.  
  879. //
  880. // clear s/z, t/z, 1/z from FP stack
  881. //
  882.     fstp %st(0)
  883.     fstp %st(0)
  884.     fstp %st(0)
  885.  
  886.     popl    %ebx                // restore spans pointer
  887. LNextSpan:
  888.     addl    $(sspan_t_size),%ebx // point to next span
  889.     movl    sspan_t_count(%ebx),%ecx
  890.     cmpl    $0,%ecx                // any more spans?
  891.     jg        LSpanLoop            // yes
  892.     jz        LNextSpan            // yes, but this one's empty
  893.  
  894.     popl    %ebx                // restore register variables
  895.     popl    %esi
  896.     popl    %edi
  897.     popl    %ebp                // restore the caller's stack frame
  898.     ret
  899.  
  900. #endif    // id386
  901.